﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Timers;
using System.Threading.Tasks;
using BTechBids.Web.Models;
using System.Diagnostics;

namespace BTechBids.Web.Singleton
{
    /// <summary>
    /// ActiveItem is a wrapper for holding an ItemVM that is currently up for bid.
    /// Also holds and manages a timer to track how long the auction should continue.
    /// </summary>
    public class ActiveItem
    {
        Singleton _instance; 


        private int timeSet;
        private Timer timer;
        private DateTime dueTime;
        private bool biddingClosed = false;

        private ItemVM ItemVM;

        /// <summary>
        /// Get updated ItemVM if the item is still active
        /// </summary>
        /// <returns>ItemVM or else void if the item is no longer active</returns>
        public ItemVM GetItemVM()
        {
            if (biddingClosed)
            {
                return default(ItemVM);
            }
            ItemVM.msRemaining = TimeRemaining();
            return ItemVM;
        }

        /// <summary>
        /// Get the finalized ItemVM once the auction has expired.
        /// </summary>
        /// <returns>ItemVM</returns>
        public ItemVM GetFinalizedItemVM()
        {
            ItemVM.msRemaining = 0;
            ItemVM.IsActive = false;
            return ItemVM;
        }

        /// <summary>
        /// ActiveItem constructor 
        /// Sets up the timer for the item but does not start the timer
        /// </summary>
        /// <param name="time">The number of milliseconds the auction should start with</param>
        /// <param name="itemVM">The ItemVM for the auction item</param>
        /// <param name="instance">The instance of the Singleton so the FinalizeAuction method can be called</param>
        public ActiveItem(int time, ItemVM itemVM, Singleton instance)
        {
            Debug.WriteLine("New active item " + itemVM.Id);

            _instance = instance;
            ItemVM = itemVM;
            ItemVM.msRemaining = time;
            timeSet = time;
            timer = new Timer(timeSet);
            timer.AutoReset = false;
            timer.Elapsed += OnTimedEvent;
        }

        /// <summary>
        /// Start the item's auction timer
        /// </summary>
        public void StartTimer()
        {
            Debug.WriteLine("timer started " + ItemVM.Id);

            dueTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)timer.Interval);
            timer.Start();
        }
        public void StopTimer()
        {
            timer.Stop();
        }

        /// <summary>
        /// Method called when timer expires to finalize the auction
        /// </summary>
        private void OnTimedEvent(Object source, ElapsedEventArgs e)
        {
            Debug.WriteLine("timer expired " + ItemVM.Id);
            biddingClosed = true;
            ItemVM.msRemaining = 0;
            _instance.FinalizeAuction(this);
        }

        /// <summary>
        /// Makes a bid on the item for the user
        /// </summary>
        /// <param name="userName">Bidder's UserName</param>
        /// <returns>Updated ItemQuickUpdateVM</returns>
        public ItemQuickUpdateVM MakeBid(string userName)
        {
            Debug.WriteLine("Bid placed " + ItemVM.Id);
            if (biddingClosed)
            {
                return default(ItemQuickUpdateVM);
            }
            int timerAdd = 10000;
            dueTime += new TimeSpan(0, 0, 0, 0, timerAdd);
            int timeRemaining = TimeRemaining();
            timer.Interval = timeRemaining + 500;
            ItemVM.msRemaining = timeRemaining;
            ItemVM.UserName = userName;
            ItemVM.Cost = Math.Round( ItemVM.Cost +  0.01, 2);


            return new ItemQuickUpdateVM()
            {
                Id = ItemVM.Id,
                Cost = ItemVM.Cost,
                UserName = ItemVM.UserName,
                msRemaining = ItemVM.msRemaining
            };

        }

        /// <summary>
        /// Time remaining for the auction
        /// </summary>
        /// <returns>Time remaining in milliseconds for the auction</returns>
        public int TimeRemaining()
        {
            return Math.Max((int)(dueTime - DateTime.Now).TotalMilliseconds, 0);
        }

    }
}